/*
 * Copyright (C) 2009 Leandro Aparecido <lehphyro@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.metalframework.util;

import java.lang.reflect.*;
import java.util.*;

import javax.persistence.*;

import net.vidageek.mirror.dsl.*;

import org.apache.commons.lang.StringUtils;

/**
 * Utilities to deal with JPA.
 * 
 * @since 1.0
 */
//TODO Refactor a little and implement support for composite primary key
public abstract class JpaUtils {

	public static boolean isEntity(Object obj) {
		// TODO See how to do this with Guice
		//Object unwrappedObj = AspectUtils.unwrapIfNecessary(obj);
		Class<?> klass = obj.getClass();
		return klass.isAnnotationPresent(Entity.class);
	}
	
	/**
	 * Retrieves the primary key column names of an entity.
	 * 
	 * @param entityClass Class of the entity
	 * @return Names of the primary keys.
	 */
	public static String[] getPrimaryKeyNames(Class<?> entityClass) {
		String name = null;
		Mirror mirror = new Mirror();
		List<Field> fields = mirror.on(entityClass).reflectAll().fieldsMatching(new Matcher<Field>() {
			@Override
			public boolean accepts(Field field) {
				return field.isAnnotationPresent(Id.class);
			}
		});
		
		for (Field field : fields) {
			if (field.isAnnotationPresent(Column.class)) {
				Column column = field.getAnnotation(Column.class);
				if ("".equals(column.name())) {
					name = field.getName();
				} else {
					name = column.name();
				}
			} else {
				name = field.getName();
			}
		}
		
		if (name == null) {
			List<Method> methods = mirror.on(entityClass).reflectAll().methodsMatching(new Matcher<Method>() {
				@Override
				public boolean accepts(Method method) {
					return method.isAnnotationPresent(Id.class);
				}
			});
			
			for (Method method : methods) {
				if (method.isAnnotationPresent(Column.class)) {
					Column column = method.getAnnotation(Column.class);
					if ("".equals(column.name())) {
						name = StringUtils.uncapitalize(method.getName().substring(3));
					} else {
						name = column.name();
					}
				} else {
					name = StringUtils.uncapitalize(method.getName().substring(3));
				}
			}
		}
		
		return new String[] { name };
	}
	
}
